package com.lt.lumentracks.handler;

import com.lt.lumentracks.constant.MessageConstant;
import com.lt.lumentracks.entity.vo.common.Result;
import com.lt.lumentracks.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLIntegrityConstraintViolationException;
import java.util.stream.Collectors;

/**
 * 全局异常处理器，处理项目中抛出的业务异常
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 捕获业务异常
     * @param ex 业务异常
     * @return 错误信息
     */
    @ExceptionHandler
    public Result<String> exceptionHandler(BaseException ex){
        log.error("异常信息：{}", ex.getMessage());
        return Result.error(ex.getMessage());
    }


    /**
     * 参数校验异常
     * 当使用@Validated或@Valid进行参数校验失败时，Spring会抛出MethodArgumentNotValidException异常
     * 其中包含一个BindingResult对象，它存储了所有校验失败的详细信息
     * <h3>BindingResult中的错误信息结构如下：</h3>
     * .getFieldErrors() --> 获取所有字段校验错误，返回List<FieldError> <br>
     *     每个FieldError对象包含： <br>
     *          field：校验失败的字段名 <br>
     *          defaultMessage：校验注解中定义的错误消息 <br>
     *          rejectedValue：被拒绝的值 <br>
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> validationExceptionHandler(MethodArgumentNotValidException ex) {
        String errorMsg = ex.getBindingResult().getFieldErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(", "));

        return Result.error("参数校验失败: " + errorMsg);
    }




    /**
     * 捕获sql异常
     * @param ex sql异常
     * @return 错误信息
     */
    @ExceptionHandler
    public Result<String> sqlExceptionHandler(SQLIntegrityConstraintViolationException ex) { // SQL完整性约束违反异常

        //Duplicate entry '17866662810' for key 'users.phone''
        String message = ex.getMessage();
        log.error("sql异常: {}", message);

        // 数据重复存在错误-->数据库中该字段有唯一索引，不能重复插入
        if (message.contains("Duplicate entry")) {
            String[] split = message.split(" ");
            String DuplicateField = split[2];
            String msg = DuplicateField + MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else {
            return Result.error("数据库" + MessageConstant.UNKNOWN_ERROR);
        }

    }


    /**
     * 捕获Redis连接异常
     */
    @ExceptionHandler(org.springframework.data.redis.RedisConnectionFailureException.class)
    public Result<String> redisConnectionFailureExceptionHandler(org.springframework.data.redis.RedisConnectionFailureException e) {
        log.error("Redis连接异常: {}", e.getMessage());
        return Result.error(MessageConstant.UNKNOWN_ERROR);
    }

}
